--- title: Blurry keywords: fastai sidebar: home_sidebar summary: "**Blurry** detects faces in photos and blurs them to increase privacy." description: "**Blurry** detects faces in photos and blurs them to increase privacy." nb_path: "00_core.ipynb" ---
{% raw %}
{% endraw %} {% raw %}
{% endraw %}

Helper function to show cv2 images in Jupyter notebook

{% raw %}
{% endraw %} {% raw %}

show_cv2[source]

show_cv2(img:ndarray)

{% endraw %}

Simple Gaussian blur

{% raw %}
{% endraw %} {% raw %}

blur[source]

blur(img:ndarray, factor=1, sigma_x=0)

{% endraw %}

Testing blur:

{% raw %}
test_img = cv2.imread('test_images/small.jpg')
assert test_img.shape == blur(test_img).shape, "Function should not change shape of array"
assert test_img.shape == blur(test_img, factor=0.5).shape, "Factors < 1 should work"
tiny = np.zeros((5,5,3), dtype = np.uint8)
assert tiny.shape == blur(tiny, factor=10).shape, "Blur function should work also when kernel size > image size"
{% endraw %} {% raw %}
def image_row(*images: list, from_cv2=True, figsize=(12,6), **kwargs) -> None :
    n_of_images = len(images)
    fig, axes = plt.subplots(1, n_of_images, figsize=figsize, **kwargs)
    #fig.tight_layout()
    for ax, img in zip(axes, images):
        if from_cv2:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        ax.imshow(img)
        ax.set_axis_off()
{% endraw %} {% raw %}
image_row(test_img, blur(test_img), blur(test_img, factor=0.5), figsize=(10,5))
{% endraw %} {% raw %}
{% endraw %} {% raw %}

pixelate[source]

pixelate(img:ndarray, factor=1)

{% endraw %}

Test pixelate:

{% raw %}
assert test_img.shape == pixelate(test_img).shape, "Function should not change shape of array"
assert len(np.unique(test_img)) > len(np.unique(pixelate(test_img))), "Number of unique colors should have been reduced"
assert len(np.unique(pixelate(test_img, factor=0.5))) > len(np.unique(pixelate(test_img, factor=5))), "Large factor should reduce number of unique colors"
tiny = np.zeros((5,5,3), dtype = np.uint8)
assert tiny.shape == pixelate(tiny).shape, "Pixelate function should also work on tiny images"
{% endraw %} {% raw %}
image_row(test_img, pixelate(test_img), pixelate(test_img, factor=1.5), figsize=(10,5))
{% endraw %}

Find faces

Using pretrained haar cascade from OpenCV.

{% raw %}
group_img = cv2.imread('test_images/group.jpg')
{% endraw %} {% raw %}
{% endraw %} {% raw %}

find_faces[source]

find_faces(img)

Finds faces in a picture and returns tuples of (x, y, w, h) for each face

{% endraw %} {% raw %}
faces = find_faces(group_img)
assert len(faces) == 7, "there should be 7 faces in the group test image"
{% endraw %}

Does it work?

{% raw %}
img = group_img.copy()
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
show_cv2(img)
{% endraw %} {% raw %}
{% endraw %} {% raw %}

blur_areas[source]

blur_areas(img, areas, factor=1, blur_func='blur')

Blurs defined areas in a cv2 image.

Inputs: img: cv2 image in BGR format areas: tuples of (x, y, w, h) factor: increase (>1.0) or decrease (<1.0) default blurring degrade_func: blur or pixelate (or any function that takes the arguments image and factor)

Returns: cv2 image in BGR format

{% endraw %} {% raw %}
{% endraw %} {% raw %}

anonymize[source]

anonymize(img, factor=1, mode='blur', convert2rgb=False)

{% endraw %} {% raw %}
{% endraw %} {% raw %}

load_img[source]

load_img(fn)

{% endraw %} {% raw %}
img = load_img('test_images/group_closer.jpg')
show_cv2(anonymize(img, factor=1, mode='pixelate'))
{% endraw %} {% raw %}
img = load_img('test_images/group_closer.jpg')
show_cv2(anonymize(img, factor=1))
{% endraw %} {% raw %}
def test_bulk(directory, **kwargs):
    path = Path(directory)
    for fn in path.ls():
        blurred = anonymize(load_img(fn), **kwargs)
        show_cv2(blurred)
{% endraw %} {% raw %}
test_bulk('test_images', factor=1, mode='pixelate')
{% endraw %}